{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# KMeans聚类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#导入必要的工具包\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.cluster import MiniBatchKMeans\n",
    "from sklearn import metrics\n",
    "\n",
    "from sklearn.decomposition import PCA\n",
    "import time\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id</th>\n",
       "      <th>locale</th>\n",
       "      <th>birthyear</th>\n",
       "      <th>gender</th>\n",
       "      <th>joinedAt</th>\n",
       "      <th>location</th>\n",
       "      <th>timezone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>3197468391</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1993</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-02T06:40:55.524Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>480.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3537982273</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1992</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-09-29T18:03:12.111Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>823183725</td>\n",
       "      <td>en_US</td>\n",
       "      <td>1975</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-06T03:14:07.149Z</td>\n",
       "      <td>Stratford  Ontario</td>\n",
       "      <td>-240.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1872223848</td>\n",
       "      <td>en_US</td>\n",
       "      <td>1991</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-11-04T08:59:43.783Z</td>\n",
       "      <td>Tehran  Iran</td>\n",
       "      <td>210.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>3429017717</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1995</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-09-10T16:06:53.132Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      user_id locale birthyear  gender                  joinedAt  \\\n",
       "0  3197468391  id_ID      1993    male  2012-10-02T06:40:55.524Z   \n",
       "1  3537982273  id_ID      1992    male  2012-09-29T18:03:12.111Z   \n",
       "2   823183725  en_US      1975    male  2012-10-06T03:14:07.149Z   \n",
       "3  1872223848  en_US      1991  female  2012-11-04T08:59:43.783Z   \n",
       "4  3429017717  id_ID      1995  female  2012-09-10T16:06:53.132Z   \n",
       "\n",
       "             location  timezone  \n",
       "0    Medan  Indonesia     480.0  \n",
       "1    Medan  Indonesia     420.0  \n",
       "2  Stratford  Ontario    -240.0  \n",
       "3        Tehran  Iran     210.0  \n",
       "4                 NaN     420.0  "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#读取训练数据\n",
    "train = pd.read_csv('users.csv')\n",
    "train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "user_id      38209\n",
       "locale       38209\n",
       "birthyear    38209\n",
       "gender       38100\n",
       "joinedAt     38152\n",
       "location     32745\n",
       "timezone     37773\n",
       "dtype: int64"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train.count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "38209"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_count = train.shape[0]\n",
    "train_count"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 38209 entries, 0 to 38208\n",
      "Data columns (total 7 columns):\n",
      "user_id      38209 non-null int64\n",
      "locale       38209 non-null object\n",
      "birthyear    38209 non-null object\n",
      "gender       38100 non-null object\n",
      "joinedAt     38152 non-null object\n",
      "location     32745 non-null object\n",
      "timezone     37773 non-null float64\n",
      "dtypes: float64(1), int64(1), object(5)\n",
      "memory usage: 2.0+ MB\n"
     ]
    }
   ],
   "source": [
    "train.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#并统计有多少不同的users（n_users）\n",
    "def get_uniqueUsers():\n",
    "    uniqueUsers = set()\n",
    "    \n",
    "    for i in range(train_count):\n",
    "        uniqueUsers.add(train.loc[i,'user_id'])\n",
    "    \n",
    "    n_events = len(uniqueUsers)\n",
    "    return n_events\n",
    "\n",
    "n_users = get_uniqueUsers()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "38209"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n_users"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>locale</th>\n",
       "      <th>birthyear</th>\n",
       "      <th>gender</th>\n",
       "      <th>joinedAt</th>\n",
       "      <th>timezone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>id_ID</td>\n",
       "      <td>1993</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-02T06:40:55.524Z</td>\n",
       "      <td>480.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>id_ID</td>\n",
       "      <td>1992</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-09-29T18:03:12.111Z</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>en_US</td>\n",
       "      <td>1975</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-06T03:14:07.149Z</td>\n",
       "      <td>-240.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>en_US</td>\n",
       "      <td>1991</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-11-04T08:59:43.783Z</td>\n",
       "      <td>210.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>id_ID</td>\n",
       "      <td>1995</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-09-10T16:06:53.132Z</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  locale birthyear  gender                  joinedAt  timezone\n",
       "0  id_ID      1993    male  2012-10-02T06:40:55.524Z     480.0\n",
       "1  id_ID      1992    male  2012-09-29T18:03:12.111Z     420.0\n",
       "2  en_US      1975    male  2012-10-06T03:14:07.149Z    -240.0\n",
       "3  en_US      1991  female  2012-11-04T08:59:43.783Z     210.0\n",
       "4  id_ID      1995  female  2012-09-10T16:06:53.132Z     420.0"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#user_id不作为聚类属性\n",
    "train = train.drop([\"user_id\"], axis=1)\n",
    "        \n",
    "#location有缺失值，粗暴抛弃\n",
    "#也可以将缺失值作为另外一类：others\n",
    "train =train.drop([\"location\"], axis=1)\n",
    "train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#特征编码\n",
    "import datetime\n",
    "import hashlib\n",
    "import locale\n",
    "\n",
    "from collections import defaultdict\n",
    "from sklearn.preprocessing import normalize\n",
    "\n",
    "class FeatureEng:\n",
    "    def __init__(self):\n",
    "         # 载入 locales\n",
    "        self.localeIdMap = defaultdict(int)\n",
    "        for i, l in enumerate(locale.locale_alias.keys()):\n",
    "          self.localeIdMap[l] = i + 1\n",
    "        \n",
    "        # 载入 gender id 字典\n",
    "        ##缺失补0\n",
    "        self.genderIdMap = defaultdict(int, {'NaN': 0, \"male\":1, \"female\":2})\n",
    "\n",
    "  \n",
    "    def getLocaleId(self, locstr):\n",
    "        return self.localeIdMap[locstr.lower()]\n",
    "\n",
    "    def getGenderId(self, genderStr):\n",
    "        return self.genderIdMap[genderStr]\n",
    "\n",
    "    def getJoinedYearMonth(self, dateString):\n",
    "        try:\n",
    "            dttm = datetime.datetime.strptime(dateString, \"%Y-%m-%dT%H:%M:%S.%fZ\")\n",
    "            #return \"\".join([str(dttm.year), str(dttm.month)])\n",
    "            return (dttm.year-2010)*12 + dttm.month\n",
    "        except:  #缺失补0\n",
    "          return 0\n",
    "\n",
    "    def getBirthYearInt(self, birthYear):\n",
    "        #缺失补0\n",
    "        try:\n",
    "          return 0 if birthYear == \"None\" else int(birthYear)\n",
    "        except:\n",
    "          return 0\n",
    "\n",
    "    def getTimezoneInt(self, timezone):\n",
    "        try:\n",
    "          return int(timezone)\n",
    "        except:  #缺失值处理\n",
    "          return 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "FE = FeatureEng()\n",
    "\n",
    "cols = ['LocaleId', 'BirthYearInt', 'GenderId', 'JoinedYearMonth', 'TimezoneInt']\n",
    "n_cols = len(cols)\n",
    "userMatrix = np.zeros((train.shape[0],n_cols), dtype=np.int)\n",
    "\n",
    "for i in range(train.shape[0]): \n",
    "    userMatrix[i, 0] = FE.getLocaleId(train.loc[i,'locale'])\n",
    "    userMatrix[i, 1] = FE.getBirthYearInt(train.loc[i,'birthyear'])\n",
    "    userMatrix[i, 2] = FE.getGenderId(train.loc[i,'gender'])\n",
    "    userMatrix[i, 3] = FE.getJoinedYearMonth(train.loc[i,'joinedAt'])\n",
    "    #userMatrix[i, 4] = FE.getCountryId(df[''])\n",
    "    userMatrix[i, 4] = FE.getTimezoneInt(train.loc[i,'timezone'])\n",
    "\n",
    "# 归一化用户矩阵\n",
    "userMatrix = normalize(userMatrix, norm=\"l1\", axis=0, copy=False)\n",
    "\n",
    "train_FE = pd.DataFrame(data=userMatrix, columns=cols)  \n",
    "#mmwrite(\"US_userMatrix\", userMatrix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>LocaleId</th>\n",
       "      <th>BirthYearInt</th>\n",
       "      <th>GenderId</th>\n",
       "      <th>JoinedYearMonth</th>\n",
       "      <th>TimezoneInt</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.000020</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000036</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.000020</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.000028</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>-0.000018</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.000028</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.000020</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   LocaleId  BirthYearInt  GenderId  JoinedYearMonth  TimezoneInt\n",
       "0  0.000020      0.000027  0.000019         0.000026     0.000036\n",
       "1  0.000020      0.000027  0.000019         0.000026     0.000031\n",
       "2  0.000028      0.000027  0.000019         0.000026    -0.000018\n",
       "3  0.000028      0.000027  0.000038         0.000027     0.000016\n",
       "4  0.000020      0.000027  0.000038         0.000026     0.000031"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_FE.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CH_score: 0.999993673762, time elaps:1642\n"
     ]
    }
   ],
   "source": [
    "n_clusters_20 = 20\n",
    "start = time.time()\n",
    "km_20 = MiniBatchKMeans(n_clusters = n_clusters_20)\n",
    "km_20.fit(train_FE)\n",
    "#保存预测结果\n",
    "y_pred_20 = km_20.predict(train_FE)\n",
    "CH_score_20 = metrics.silhouette_score(train_FE,y_pred_20)\n",
    "end = time.time()\n",
    "print(\"CH_score: {}, time elaps:{}\".format(CH_score_20, int(end-start)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CH_score: 0.73118199101, time elaps:1550\n"
     ]
    }
   ],
   "source": [
    "n_clusters_40 = 40\n",
    "start = time.time()\n",
    "km_40 = MiniBatchKMeans(n_clusters = n_clusters_40)\n",
    "km_40.fit(train_FE)\n",
    "#保存预测结果\n",
    "y_pred_40 = km_40.predict(train_FE)\n",
    "CH_score_40 = metrics.silhouette_score(train_FE,y_pred_40)\n",
    "end = time.time()\n",
    "print(\"CH_score: {}, time elaps:{}\".format(CH_score_40, int(end-start)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CH_score: 0.665654961902, time elaps:1325\n"
     ]
    }
   ],
   "source": [
    "n_clusters_80 = 80\n",
    "start = time.time()\n",
    "km_80 = MiniBatchKMeans(n_clusters = n_clusters_80)\n",
    "km_80.fit(train_FE)\n",
    "#保存预测结果\n",
    "y_pred_80 = km_80.predict(train_FE)\n",
    "CH_score_80 = metrics.silhouette_score(train_FE,y_pred_80)\n",
    "end = time.time()\n",
    "print(\"CH_score: {}, time elaps:{}\".format(CH_score_80, int(end-start)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CH_score: 0.807887339952, time elaps:1757\n"
     ]
    }
   ],
   "source": [
    "n_clusters_10 = 10\n",
    "start = time.time()\n",
    "km_10 = MiniBatchKMeans(n_clusters = n_clusters_10)\n",
    "km_10.fit(train_FE)\n",
    "#保存预测结果\n",
    "y_pred_10 = km_10.predict(train_FE)\n",
    "CH_score_10 = metrics.silhouette_score(train_FE,y_pred_10)\n",
    "end = time.time()\n",
    "print(\"CH_score: {}, time elaps:{}\".format(CH_score_10, int(end-start)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "成果绘图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0xe7c1438>]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nReR/AHK2PcIGR9Z1AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0xe7a3cc0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "Ks = np.int_([n_clusters_10,n_clusters_20,n_clusters_40,n_clusters_80])\n",
    "Ch_scores =  np.float_([CH_score_10,CH_score_20,CH_score_40,CH_score_80])\n",
    "plt.plot(Ks, Ch_scores, 'b-')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "输出结果文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train[\"y_pred_20\"]=y_pred_20"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>locale</th>\n",
       "      <th>birthyear</th>\n",
       "      <th>gender</th>\n",
       "      <th>joinedAt</th>\n",
       "      <th>timezone</th>\n",
       "      <th>y_pred_20</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>id_ID</td>\n",
       "      <td>1993</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-02T06:40:55.524Z</td>\n",
       "      <td>480.0</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>id_ID</td>\n",
       "      <td>1992</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-09-29T18:03:12.111Z</td>\n",
       "      <td>420.0</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>en_US</td>\n",
       "      <td>1975</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-06T03:14:07.149Z</td>\n",
       "      <td>-240.0</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>en_US</td>\n",
       "      <td>1991</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-11-04T08:59:43.783Z</td>\n",
       "      <td>210.0</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>id_ID</td>\n",
       "      <td>1995</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-09-10T16:06:53.132Z</td>\n",
       "      <td>420.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  locale birthyear  gender                  joinedAt  timezone  y_pred_20\n",
       "0  id_ID      1993    male  2012-10-02T06:40:55.524Z     480.0          2\n",
       "1  id_ID      1992    male  2012-09-29T18:03:12.111Z     420.0          2\n",
       "2  en_US      1975    male  2012-10-06T03:14:07.149Z    -240.0          3\n",
       "3  en_US      1991  female  2012-11-04T08:59:43.783Z     210.0          7\n",
       "4  id_ID      1995  female  2012-09-10T16:06:53.132Z     420.0          0"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "train.to_csv(\"result.csv\", index = False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
